package org.zjx.core.builder;

import org.zjx.core.DecisionContext;
import org.zjx.core.DecisionNode;
import org.zjx.core.GameAction;
import org.zjx.core.nodes.*;
import org.zjx.core.state.StateAccessor;
import org.zjx.core.state.StateComponent;

import java.util.*;
import java.util.function.*;

/**
 * 改进后的决策树构建器，提供更直观的API和更好的分支支持
 */
public class DecisionTreeBuilder {
    private DecisionNode root;
    private DecisionNode lastNode;
    private final Deque<ConditionNode> conditionStack = new ArrayDeque<>();
    private final Map<String, Object> builderParams = new HashMap<>();

    // ========== 基础构建方法 ==========

    /**
     * 添加条件分支
     */
    public DecisionTreeBuilder when(BiPredicate<StateAccessor, Map<String, Object>> condition) {
        ConditionNode node = new ConditionNode(condition, null, null);
        linkNode(node);
        conditionStack.push(node);
        return this;
    }


    // 添加流畅的DSL方法
    public DecisionTreeBuilder whenHasComponent(Class<? extends StateComponent> component) {
        return when((accessor, params) -> accessor.containsComponent(component));
    }

    public DecisionTreeBuilder when(Predicate<DecisionContext> condition) {
        return when((accessor, params) -> condition.test(
                new DecisionContext(accessor, params)
        ));
    }

    /**
     * 添加动作节点
     */
    public DecisionTreeBuilder action(GameAction action) {
        return then(new ActionNode(action, null));
    }

    public DecisionTreeBuilder action(String actionId, Consumer<ActionBuilder> config) {
        ActionBuilder builder = new ActionBuilder(actionId);
        config.accept(builder);
        return then(builder.build());
    }


    // 添加子树支持
    public DecisionTreeBuilder subtree(String treeId, Consumer<DecisionTreeBuilder> config) {
        DecisionTreeBuilder subtreeBuilder = new DecisionTreeBuilder();
        config.accept(subtreeBuilder);
        return then(new SubTreeNode(subtreeBuilder.build(), null, null));
    }

    /**
     * 添加决策节点
     */
    public DecisionTreeBuilder then(DecisionNode node) {
        linkNode(node);
        return this;
    }

    /**
     * 结束当前条件分支
     */
    public DecisionTreeBuilder endCondition() {
        if (!conditionStack.isEmpty()) {
            conditionStack.pop();
        }
        return this;
    }

    // ========== 高级构建方法 ==========

    /**
     * 构建完整分支结构
     */
    public DecisionTreeBuilder branch(
            BiPredicate<StateAccessor, Map<String, Object>> condition,
            Consumer<DecisionTreeBuilder> trueBranch,
            Consumer<DecisionTreeBuilder> falseBranch) {

        ConditionNode node = new ConditionNode(condition, null, null);
        linkNode(node);

        // 构建true分支
        DecisionTreeBuilder trueBuilder = new DecisionTreeBuilder();
        trueBranch.accept(trueBuilder);
        node.setTrueBranch(trueBuilder.build());

        // 构建false分支
        if (falseBranch != null) {
            DecisionTreeBuilder falseBuilder = new DecisionTreeBuilder();
            falseBranch.accept(falseBuilder);
            node.setFalseBranch(falseBuilder.build());
        }

        return this;
    }

    public DecisionTreeBuilder branch(
            Predicate<DecisionContext> condition,
            Consumer<DecisionTreeBuilder> trueBranch,
            Consumer<DecisionTreeBuilder> falseBranch) {

        return branch((accessor, params) -> condition.test(
                new DecisionContext(accessor, params)
        ), trueBranch, falseBranch);
    }


    /**
     * 简化if-then结构
     */
    public DecisionTreeBuilder ifThen(
            BiPredicate<StateAccessor, Map<String, Object>> condition,
            GameAction trueAction) {
        return branch(condition, b -> b.action(trueAction), null);
    }

    /**
     * 简化if-then-else结构
     */
    public DecisionTreeBuilder ifThenElse(
            BiPredicate<StateAccessor, Map<String, Object>> condition,
            GameAction trueAction,
            GameAction falseAction) {
        return branch(condition,
                b -> b.action(trueAction),
                b -> b.action(falseAction));
    }

    /**
     * 构建序列执行节点
     */
    public DecisionTreeBuilder sequence(Consumer<DecisionTreeBuilder> sequence) {
        DecisionTreeBuilder sequenceBuilder = new DecisionTreeBuilder();
        sequence.accept(sequenceBuilder);
        linkNode(sequenceBuilder.build());
        return this;
    }

    /**
     * 构建并行执行节点
     */
    public DecisionTreeBuilder parallel(Consumer<ParallelBuilder> configurator) {
        ParallelBuilder builder = new ParallelBuilder();
        configurator.accept(builder);
        linkNode(builder.build());
        return this;
    }

    /**
     * 构建随机选择节点
     */
    public DecisionTreeBuilder random(Consumer<RandomBuilder> configurator) {
        RandomBuilder builder = new RandomBuilder();
        configurator.accept(builder);
        linkNode(builder.build());
        return this;
    }

    // ========== 内部方法 ==========

    private void linkNode(DecisionNode node) {
        if (root == null) {
            root = node;
        } else {
            if (lastNode instanceof ConditionNode) {
                ((ConditionNode) lastNode).setTrueBranch(node);
            } else if (lastNode instanceof ActionNode) {
                ((ActionNode) lastNode).setNext(node);
            }
        }
        lastNode = node;
    }

    public DecisionNode build() {
        return root;
    }

    // ========== 内部构建器类 ==========

    public static class ParallelBuilder {
        private final List<DecisionNode> nodes = new ArrayList<>();

        public ParallelBuilder branch(Consumer<DecisionTreeBuilder> configurator) {
            DecisionTreeBuilder branchBuilder = new DecisionTreeBuilder();
            configurator.accept(branchBuilder);
            nodes.add(branchBuilder.build());
            return this;
        }

        public DecisionNode build() {
            return new ParallelNode(nodes);
        }
    }

    public static class RandomBuilder {
        private final List<DecisionNode> candidates = new ArrayList<>();

        public RandomBuilder option(Consumer<DecisionTreeBuilder> configurator) {
            DecisionTreeBuilder optionBuilder = new DecisionTreeBuilder();
            configurator.accept(optionBuilder);
            candidates.add(optionBuilder.build());
            return this;
        }

        public DecisionNode build() {
            return new RandomSelectorNode(candidates);
        }
    }
}